package com.mths.server.controller;

import java.sql.SQLException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;

import org.apache.commons.fileupload.FileItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mths.client.constant.DocumentConstant;
import com.mths.client.controller.CompanyDocumentController;
import com.mths.client.dto.CompanyDocumentDTO;
import com.mths.client.dto.CompanyDocumentData;
import com.mths.client.util.FileDownloadItem;
import com.mths.client.util.ListItem;
import com.mths.server.dao.ActionLogDAO;
import com.mths.server.dao.CompanyDAO;
import com.mths.server.dao.CompanyDocumentDAO;
import com.mths.server.dao.DocumentMetaDAO;
import com.mths.server.dao.DocumentTypeDAO;
import com.mths.server.dao.MetaDataDAO;
import com.mths.server.dao.UserDAO;
import com.mths.server.entity.CompanyDocument;
import com.mths.server.entity.CompanyDocumentMeta;
import com.mths.server.entity.DocumentDBStore;
import com.mths.server.entity.MetaData;
import com.mths.server.entity.User;
import com.mths.server.util.ServerConvertUtil;
import com.mths.server.util.SessionUtil;

/**
 * The server side implementation of the RPC service.
 */
@Service("companyDocumentController")
@Transactional
public class CompanyDocumentControllerImpl extends AbstractController implements CompanyDocumentController {

	@Autowired
	private transient DocumentTypeDAO		documentTypeDAO;

	@Autowired
	private transient DocumentMetaDAO		documentMetaDAO;

	@Autowired
	private transient MetaDataDAO			metaDataDAO;

	@Autowired
	private transient CompanyDocumentDAO	compDocDAO;

	@Autowired
	private transient CompanyDAO			companyDAO;

	@Autowired
	private transient UserDAO				userDAO;

	@Autowired
	private transient ActionLogDAO			actionLogDAO;

	@Override
	public void saveDocument(CompanyDocumentDTO dto) throws Exception {

		// company exist control
		CompanyDocument companyDocument = null;
		if (dto.getObjid() != null)
			companyDocument = compDocDAO.findByOid(dto.getObjid());
		if (companyDocument == null)
			companyDocument = new CompanyDocument();

		// yetkisiz islem kontrolu
		if (!SessionUtil.getSessionUser().getAuthorizedCompanyOidList().contains(SessionUtil.getSessionUser().getSelectedCompanyOid())) {
			throw new Exception("İşlem yapmaya çalıştığınız şirket yetkili olduğunuz şirketler arasında değildir.");
		}

		DocumentDBStore dbStore = createDBStore(dto.getFileSessionKey());

		List<MetaData> metaDataList = documentMetaDAO.loadMetaWithParamByDocTypeOid(dto.getDocType());
		metaDataList
				.addAll(metaDataDAO.loadMetaDataByUniquId(new String[] { DocumentConstant.UPLOAD_USER, DocumentConstant.PROCESS_DATE }));
		List<CompanyDocumentMeta> compDocMetaList = new ArrayList<CompanyDocumentMeta>();
		for (MetaData metaData : metaDataList) {
			CompanyDocumentMeta compDocMeta = new CompanyDocumentMeta();
			compDocMeta.setMetaData(metaData);
			compDocMeta.setCompanyDocument(companyDocument);
			compDocMeta.setMetaValue(dto.getFieldValueMap().get(metaData.getFieldId()));
			compDocMetaList.add(compDocMeta);
		}

		companyDocument.setCompany(companyDAO.findByOid(SessionUtil.getSessionUser().getSelectedCompanyOid()));
		companyDocument.setDocumentType(documentTypeDAO.findByOid(dto.getDocType()));
		companyDocument.setDocument(dbStore);
		companyDocument.setCompanyDocumentMetaList(compDocMetaList);

		companyDocument = compDocDAO.persistOrUpdate(companyDocument);

		// log for this process
		actionLogDAO.documentInsert(companyDocument.getDocumentType().getObjid(), companyDocument.getDocument().getObjid());

		// dosya sessiondan siliniyor
		SessionUtil.session.removeAttribute(dto.getFileSessionKey());
	}

	private DocumentDBStore createDBStore(String fileSessionKey) throws Exception {
		FileItem fileItem = (FileItem) SessionUtil.session.getAttribute(fileSessionKey);
		if (fileItem == null) {
			throw new Exception("Dosya ile yüklenemedi, tekrar deneyiniz");
		}
		DocumentDBStore dbStore = new DocumentDBStore();
		dbStore.setDocument(ServerConvertUtil.fileItem2Blob(fileItem));
		dbStore.setContentType(fileItem.getContentType());
		dbStore.setFileName(fileItem.getName());
		dbStore.setFormattedSize(ServerConvertUtil.formattedByte(fileItem.get().length));
		return dbStore;
	}

	@Override
	public List<CompanyDocumentData> loadCompanyDocuments(String string) {
		List<CompanyDocument> companyDocumentList = compDocDAO.loadCompanyDocument(SessionUtil.getSessionUser().getSelectedCompanyOid());
		if (companyDocumentList == null || companyDocumentList.isEmpty())
			return null;

		// sort list by turkish
		sortList(companyDocumentList);

		List<CompanyDocumentData> documentDataList = new ArrayList<CompanyDocumentData>();
		for (CompanyDocument companyDocument : companyDocumentList) {
			CompanyDocumentData documentData = new CompanyDocumentData();
			documentData.setDocDbStoreOid(companyDocument.getDocument().getObjid());
			documentData.setDocSize(companyDocument.getDocument().getFormattedSize());
			documentData.setDocType(companyDocument.getDocumentType().getName());
			documentData.setDocTypeOid(companyDocument.getDocumentType().getObjid());
			documentData.setFileName(companyDocument.getDocument().getFileName());
			documentData.setDocDbStoreOid(companyDocument.getDocument().getObjid());

			List<ListItem> metaDataValueList = new ArrayList<ListItem>();
			if (companyDocument.getCompanyDocumentMetaList() != null) {
				for (CompanyDocumentMeta docMeta : companyDocument.getCompanyDocumentMetaList()) {
					String metaValue = docMeta.getMetaValue();
					if (docMeta.getMetaData().getFieldId().equals(DocumentConstant.UPLOAD_USER)) {
						User user = userDAO.findByOid(docMeta.getMetaValue());
						if (user != null) {
							metaValue = user.getFullName();
						}
					}
					metaDataValueList.add(new ListItem(docMeta.getMetaData().getFieldName(), metaValue));
				}
			}
			documentData.setMetaDataValueList(metaDataValueList);
			documentDataList.add(documentData);
		}
		return documentDataList;
	}

	private void sortList(List<CompanyDocument> companyDocumentList) {
		Collections.sort(companyDocumentList, new Comparator<CompanyDocument>() {
			@Override
			public int compare(CompanyDocument o1, CompanyDocument o2) {
				Collator trCollator = Collator.getInstance(new Locale("tr", "TR"));
				return trCollator.compare(o1.getDocumentType().getName(), o2.getDocumentType().getName());
			}
		});
	}

	@Override
	public FileDownloadItem getDocumentDBStoreByOid(String fileDbStoreOid) {
		DocumentDBStore documentDBStore = compDocDAO.findDocumentDBStoreByOid(fileDbStoreOid);
		FileDownloadItem downloadItem = new FileDownloadItem();

		Long length;
		byte[] data = "".getBytes();
		try {
			length = documentDBStore.getDocument().length();
			data = documentDBStore.getDocument().getBytes(1, length.intValue());
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		downloadItem.setFileContent(data);
		downloadItem.setFileContentType(documentDBStore.getContentType());
		downloadItem.setFileName(documentDBStore.getFileName());
		return downloadItem;
	}
}